home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / SciAn / src / ScianObjFunctions.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  42KB  |  1,591 lines

  1. /*ScianObjFunctions.c
  2.   Eric Pepke
  3.   April 9, 1992
  4.   Definitions and routines for per-object functions
  5. */
  6.  
  7. #include "Scian.h"
  8. #include "ScianTypes.h"
  9. #include "ScianLists.h"
  10. #include "ScianWindows.h"
  11. #include "ScianColors.h"
  12. #include "ScianIDs.h"
  13. #include "ScianObjWindows.h"
  14. #include "ScianButtons.h"
  15. #include "ScianErrors.h"
  16. #include "ScianDraw.h"
  17. #include "ScianControls.h"
  18. #include "ScianArrays.h"
  19. #include "ScianScripts.h"
  20. #include "ScianVisWindows.h"
  21. #include "ScianIcons.h"
  22. #include "ScianEvents.h"
  23. #include "ScianStyle.h"
  24. #include "ScianObjFunctions.h"
  25. #include "ScianHelp.h"
  26. #include "ScianFilters.h"
  27. #include "ScianFileSystem.h"
  28. #include "ScianSockets.h"
  29. #include "ScianSnap.h"
  30. #include "ScianMenus.h"
  31. #include "ScianFontSystem.h"
  32. #include "ScianDialogs.h"
  33. #include "ScianDatabase.h"
  34. #include "ScianSymbols.h"
  35.  
  36.  
  37. /*Sizes for text menu*/
  38. int textSizes[] =
  39.     {
  40.     9,
  41.     10,
  42.     12,
  43.     14,
  44.     18,
  45.     24,
  46.     36,
  47.     48,
  48.     72
  49.     };
  50.  
  51. typedef struct
  52.     {
  53.     char *name;
  54.     void (*setupRoutine)();
  55.     void (*finishRoutine)();
  56.     NameTyp funcMessage;
  57.     char *buttonHelp;
  58.     char *menuHelp;
  59.     char *scriptPrefix, *scriptPostfix;
  60.     Bool varPostfix;    /*True iff postfix is variable*/
  61.     ObjPtr postfixObject;    /*Postfix object, used instead of postfix string*/
  62.     int isUsed;
  63.     Bool multObjects;    /*True iff mult objects ok*/
  64.     ObjPtr whichMenu;    /*Which menu function is in*/
  65.     int menuGroup;        /*Menu group*/
  66.     ObjPtr objectsToDo;    /*List of current objects to do this function on*/
  67.     } ObjFunction;
  68.  
  69. int nObjFunctions = 0;            /*Number of object functions*/
  70.  
  71. static ObjPtr objectActionClass;    /*Class for all object actions*/
  72.  
  73. static ObjFunction *objFunctions = NULL;
  74. static int globalFuncNum;
  75. static ObjPtr undoList;            /*List of undo operations*/
  76. static ObjPtr undoClass;        /*Class of undo's*/
  77. static ObjPtr curUndo = NULLOBJ;    /*Current undo being built up*/
  78. static int curUndoType = 0;        /*Current type of undo being built*/
  79.  
  80. #ifdef PROTO
  81. ObjPtr NewUndo(int undoType)
  82. #else
  83. ObjPtr NewUndo(undoType)
  84. int undoType;
  85. #endif
  86. {
  87.     ObjPtr retVal;
  88.  
  89.     retVal = NewObject(undoClass, 0L);
  90.     SetVar(retVal, UNDOTYPE, NewInt(undoType));
  91.  
  92.     /*Do initialization of undo*/
  93.     switch(undoType)
  94.     {
  95.     case UT_CHANGESNAPSHOT:
  96.         SetVar(retVal, OLDSNAPSHOTS, NewList());
  97.         break;
  98.     }
  99.  
  100.     return retVal;
  101. }
  102.  
  103. #ifdef PROTO
  104. void BeginUndo(int undoType)
  105. #else
  106. void BeginUndo(undoType)
  107. int undoType;
  108. #endif
  109. /*Begins an undo to build up*/
  110. {
  111.     curUndo = NewUndo(undoType);
  112.     curUndoType = undoType;
  113. }
  114.  
  115. #ifdef PROTO
  116. void SaveSnapshotForUndo(ObjPtr object)
  117. #else
  118. void SaveSnapshotForUndo(object)
  119. ObjPtr object;
  120. #endif
  121. /*Saves a snapshot of object in the current undo*/
  122. {
  123.     ObjPtr list;
  124.  
  125.     if (!curUndo) return;
  126.  
  127.     list = GetVar(curUndo, OLDSNAPSHOTS);
  128.     if (!list)
  129.     {
  130.     list = NewList();
  131.     SetVar(curUndo, OLDSNAPSHOTS, list);
  132.     }
  133.     PrefixList(list, TakeSnapshot(object));
  134. }
  135.  
  136. void EndUndo()
  137. /*Ends an undo in progress*/
  138. {
  139.     if (!curUndo) return;
  140.     EmptyList(undoList);
  141.     PrefixList(undoList, curUndo);
  142.     curUndo = NULLOBJ;
  143. }
  144.  
  145. #ifdef PROTO
  146. void SaveForUndo(ObjPtr object)
  147. #else
  148. void SaveForUndo(object)
  149. ObjPtr object;
  150. #endif
  151. /*Saves object for undo later*/
  152. {
  153.     ObjPtr snapshot, undo, list;
  154.  
  155.     if (object)
  156.     {
  157.     BeginUndo(UT_CHANGESNAPSHOT);
  158.     SaveSnapshotForUndo(object);
  159.     EndUndo();
  160.     }
  161. }
  162.  
  163. void Undo()
  164. /*Do the undo operation*/
  165. {
  166.     ThingListPtr runner;
  167.  
  168.     runner = LISTOF(undoList);
  169.     if (runner && runner -> thing)
  170.     {
  171.     /*There is something to undo*/
  172.     int undoType;
  173.     ObjPtr var, undo;
  174.  
  175.     undo = runner -> thing;
  176.     var = GetIntVar("Undo", undo, UNDOTYPE);
  177.     if (!var) return;
  178.  
  179.     undoType = GetInt(var);
  180.     switch(undoType)
  181.     {
  182.         case UT_CHANGESNAPSHOT:
  183.         {
  184.             ObjPtr oldSnapshots, oldSnap, object;
  185.             ThingListPtr snapRunner;
  186.  
  187.             oldSnapshots = GetListVar("Undo", undo, OLDSNAPSHOTS);
  188.             if (!oldSnapshots) return;
  189.  
  190.             /*Set up inverse undo*/
  191.             BeginUndo(UT_CHANGESNAPSHOT);
  192.  
  193.             snapRunner = LISTOF(oldSnapshots);
  194.             while (snapRunner)
  195.             {
  196.             oldSnap = snapRunner -> thing;
  197.             object = GetVar(oldSnap, REPOBJ);
  198.  
  199.             SaveSnapshotForUndo(object);
  200.             ApplySnapshot(oldSnap);
  201.  
  202.             snapRunner = snapRunner -> next;
  203.             }
  204.  
  205.             EndUndo();
  206.         }
  207.         break;
  208.     }
  209.  
  210.     }
  211. }
  212.  
  213. #ifdef PROTO
  214. int NameToObjFunction(char *name)
  215. #else
  216. int NameToObjFunction(name);
  217. char *name;
  218. #endif
  219. /*Converts a name to a function number, or -1*/
  220. {
  221.     int funcNum;
  222.  
  223.     /*Search for the named function*/
  224.     for (funcNum = 0; funcNum < nObjFunctions; ++funcNum)
  225.     {
  226.     if (0 == strcmp2(name, objFunctions[funcNum] . name))
  227.     {
  228.         break;
  229.     }
  230.     }
  231.  
  232.     if (funcNum >= nObjFunctions)
  233.     {
  234.     /*Not found, too bad.*/
  235.     return -1;
  236.     }
  237.     return funcNum;
  238. }
  239.  
  240.  
  241. #ifdef PROTO
  242. ObjPtr DefineObjFunction(char *funcName, char *menuName, void (*setupRoutine)(), NameTyp funcMessage,
  243.     void (*finishRoutine)(), char *scriptPrefix, char *scriptPostfix,
  244.     Bool multObjects, char *buttonHelp,
  245.     char *menuHelp, ObjPtr whichMenu, int menuGroup, Bool varPostfix)
  246. #else
  247. ObjPtr DefineObjFunction(funcName, menuName, setupRoutine, funcMessage,
  248.     finishRoutine, scriptPrefix, scriptPostfix,
  249.     multObjects, buttonHelp,
  250.     menuHelp, whichMenu, menuGroup, varPostfix)
  251. char *funcName;
  252. char *menuName;
  253. void (*setupRoutine)();
  254. NameTyp funcMessage;
  255. void (*finishRoutine)();
  256. char *scriptPrefix;
  257. char *scriptPostfix;
  258. Bool multObjects;
  259. char *buttonHelp;
  260. char *menuHelp;
  261. int menuGroup;
  262. ObjPtr whichMenu;
  263. Bool varPostfix;
  264. #endif
  265. /*Defines an object function
  266.     funcName        is the name of the function for the menu and buttons
  267.     menuName        is an alternate name for menus
  268.     setupRoutine    is a routine to call at the beginning, or 0
  269.     funcMessage        is a message to send to every selected object as a single argument
  270.     finishRoutine   is a routine to call when finished
  271.     scriptPrefix    is the script portion to prefix to the object names
  272.     scriptPostfix   is the script portion to postfix to the object names
  273.     multObjects        is true iff it accepts multiple objects
  274.     buttonHelp        is the help string for a button, or nothing for no button
  275.     menuHelp        is the help string for a menu
  276.     whichMenu        is which menu to use
  277.     menuGroup        is the group within the menu
  278.     varPostfix        is true iff the postfix is variable, in which case what
  279.             is actually there will be passed to the action method
  280.  
  281.  More than 1 obj function can only be defined if it is a varPostfix function.
  282.  %s in the help will indicate use of postFix value
  283.  
  284.  Returns the action produced.
  285. */
  286. {
  287.     ObjPtr action = NULLOBJ;        /*The action*/
  288.  
  289.     if (NameToObjFunction(funcName) < 0)
  290.     {
  291.     if (nObjFunctions)
  292.     {
  293.     objFunctions = Realloc(objFunctions, (nObjFunctions + 1) * sizeof(ObjFunction));
  294.     }
  295.     else
  296.     {
  297.     objFunctions = Alloc((nObjFunctions + 1) * sizeof(ObjFunction));
  298.     }
  299.  
  300.     if (funcName)
  301.     {
  302.     objFunctions[nObjFunctions] . name = Alloc(strlen(funcName) + 1);
  303.     strcpy(objFunctions[nObjFunctions] . name, funcName);
  304.     }
  305.     else
  306.     {
  307.     objFunctions[nObjFunctions] . name = (char *) 0;
  308.     }
  309.     objFunctions[nObjFunctions] . setupRoutine = setupRoutine;
  310.     objFunctions[nObjFunctions] . funcMessage = funcMessage;
  311.     objFunctions[nObjFunctions] . finishRoutine = finishRoutine;
  312.     objFunctions[nObjFunctions] . whichMenu = whichMenu;
  313.     objFunctions[nObjFunctions] . multObjects = multObjects;
  314.     AddToReferenceList(objFunctions[nObjFunctions] . objectsToDo = NewList());
  315.     if (scriptPrefix)
  316.     {
  317.     objFunctions[nObjFunctions] . scriptPrefix = Alloc(strlen(scriptPrefix) + 1);
  318.     strcpy(objFunctions[nObjFunctions] . scriptPrefix, scriptPrefix);
  319.     }
  320.     else
  321.     {
  322.     objFunctions[nObjFunctions] . scriptPrefix = (char *) 0;
  323.     }
  324.     objFunctions[nObjFunctions] . postfixObject = NULLOBJ;
  325.     if (scriptPostfix)
  326.     {
  327.     objFunctions[nObjFunctions] . scriptPostfix = Alloc(strlen(scriptPostfix) + 1);
  328.     strcpy(objFunctions[nObjFunctions] . scriptPostfix, scriptPostfix);
  329.     }
  330.     else
  331.     {
  332.     objFunctions[nObjFunctions] . scriptPostfix = (char *) 0;
  333.     }
  334.     objFunctions[nObjFunctions] . varPostfix = varPostfix;
  335.     if (buttonHelp)
  336.     {
  337.     objFunctions[nObjFunctions] . buttonHelp = Alloc(strlen(buttonHelp) + 1);
  338.     strcpy(objFunctions[nObjFunctions] . buttonHelp, buttonHelp);
  339.     }
  340.     else
  341.     {
  342.     objFunctions[nObjFunctions] . buttonHelp = (char *) 0;
  343.     }
  344.     if (menuHelp)
  345.     {
  346.     objFunctions[nObjFunctions] . menuHelp = Alloc(strlen(menuHelp) + 1);
  347.     strcpy(objFunctions[nObjFunctions] . menuHelp, menuHelp);
  348.     }
  349.     else
  350.     {
  351.     objFunctions[nObjFunctions] . menuHelp = (char *) 0;
  352.     }
  353.     objFunctions[nObjFunctions] . menuGroup = menuGroup;
  354.  
  355.  
  356.     ++nObjFunctions;
  357.     }
  358.  
  359.     if (whichMenu)
  360.     {
  361.     /*Put it on whichMenu*/
  362.     char *s, *d;
  363.  
  364.     /*Go through menuHelp*/
  365.     s = menuHelp;
  366.     d = tempStr;
  367.     while (*s)
  368.     {
  369.         if (*s == '%' && *(s + 1) == 's')
  370.         {
  371.         if (scriptPostfix)
  372.         {
  373.             strcpy(d, scriptPostfix);
  374.         }
  375.         ++s;
  376.         ++s;
  377.         while (*d) ++d;
  378.         }
  379.         else
  380.         {
  381.         *d++ = *s++;
  382.         }
  383.     }
  384.     *d = 0;
  385.  
  386.     action = NewAction(menuName ? menuName : funcName, objectActionClass);
  387.     SetVar(action, FUNCNAME, NewString(funcName));
  388.     SetVar(action, HELPSTRING, NewString(tempStr));
  389.     if (varPostfix && scriptPostfix)
  390.     {
  391.         SetVar(action, VALUE, NewString(scriptPostfix));
  392.     }
  393.     AddMenuItem(whichMenu, action, menuGroup);
  394.     }
  395.     return action;
  396. }
  397.  
  398. static void StartObjFunction(funcNum)
  399. int funcNum;
  400. /*Starts object function funcNum*/
  401. {
  402.     globalFuncNum = funcNum;
  403.  
  404.     /*Do the first bit*/
  405.     if (objFunctions[funcNum] . setupRoutine)
  406.     {
  407.     InhibitLogging(true);
  408.     (*(objFunctions[funcNum] . setupRoutine))();
  409.     InhibitLogging(false);
  410.     }
  411. }
  412.  
  413. static ObjPtr DoObjFunctionOnObject(object)
  414. ObjPtr object;
  415. /*Does an object function in globalFuncNum, if it is appropriate, on object.  
  416.   Designed to be passable to ForAllSelectedObjects*/
  417. {
  418.     FuncTyp method;
  419.     ObjPtr retVal = ObjFalse;
  420.  
  421.     method = GetMethod(object, objFunctions[globalFuncNum] . funcMessage);
  422.     if (method)
  423.     {
  424.     InhibitLogging(true);
  425.     if (objFunctions[globalFuncNum] . varPostfix)
  426.     {
  427.         if (objFunctions[globalFuncNum] . scriptPostfix)
  428.         {
  429.         retVal = (*method)(object, NewString(objFunctions[globalFuncNum] . scriptPostfix));
  430.         }
  431.         else
  432.         {
  433.         retVal = (*method)(object, objFunctions[globalFuncNum] . postfixObject);
  434.         }
  435.     }
  436.     else
  437.     {
  438.         retVal = (*method)(object);
  439.     }
  440.     InhibitLogging(false);
  441.     }
  442.     return retVal;
  443. }
  444.  
  445. static void FinishObjFunction()
  446. /*Finishes object function funcNum*/
  447. {
  448.     /*Do the last bit*/
  449.     if (objFunctions[globalFuncNum] . finishRoutine)
  450.     {
  451.     InhibitLogging(true);
  452.     (*(objFunctions[globalFuncNum] . finishRoutine))();
  453.     InhibitLogging(false);
  454.     }
  455. }
  456.  
  457. static Bool firstLoggedObject;
  458.  
  459. ObjPtr LogSpacedObject(object)
  460. ObjPtr object;
  461. /*Logs all the objects with spaces*/
  462. {
  463.     if (!firstLoggedObject)
  464.     {
  465.     Log(",");
  466.     }
  467.     else
  468.     {
  469.     firstLoggedObject = false;
  470.     if (objFunctions[globalFuncNum] . scriptPrefix)
  471.     {
  472.         Log(objFunctions[globalFuncNum] . scriptPrefix);
  473.     }
  474.     }
  475.     Log(" ");
  476.     LogObjectName(object);
  477.     return ObjTrue;
  478. }
  479.  
  480. void LogObjFunction(name, list)
  481. char *name;
  482. ObjPtr list;
  483. /*Logs the object function name on list*/
  484. {
  485.     int funcNum;
  486.  
  487.     FlushKeystrokes();
  488.  
  489.     funcNum = NameToObjFunction(name);
  490.     if (funcNum < 0)
  491.     {
  492.     /*No valid function*/
  493.     return;
  494.     }
  495.  
  496.     /*Emit the log*/
  497.     if (logging)
  498.     {
  499.     ThingListPtr runner;
  500.     globalFuncNum = funcNum;
  501.     firstLoggedObject = true;
  502.     runner = LISTOF(list);
  503.     while (runner)
  504.     {
  505.         LogSpacedObject(runner -> thing);
  506.         runner = runner -> next;
  507.     }
  508.  
  509.     if (!firstLoggedObject)
  510.     {
  511.         if (objFunctions[funcNum] . scriptPostfix)
  512.         {
  513.         Log(" ");
  514.         Log(objFunctions[funcNum] . scriptPostfix);
  515.         }
  516.         else if (objFunctions[funcNum] . postfixObject)
  517.         {
  518.         Log(" ");
  519.         LogObjectName(objFunctions[funcNum] . postfixObject);
  520.         }
  521.         Log("\n");
  522.     }
  523.     }
  524. }
  525.  
  526. void LogSelectedObjFunction(name)
  527. char *name;
  528. /*Logs the object function name on all selected objects*/
  529. {
  530.     int funcNum;
  531.  
  532.     FlushKeystrokes();
  533.  
  534.     funcNum = NameToObjFunction(name);
  535.     if (funcNum < 0)
  536.     {
  537.     /*No valid function*/
  538.     return;
  539.     }
  540.  
  541.     /*Emit the log*/
  542.     if (logging)
  543.     {
  544.     globalFuncNum = funcNum;
  545.     firstLoggedObject = true;
  546.     ForAllSelectedObjects(LogSpacedObject);
  547.  
  548.     if (!firstLoggedObject)
  549.     {
  550.         if (objFunctions[funcNum] . scriptPostfix)
  551.         {
  552.         Log(" ");
  553.         Log(objFunctions[funcNum] . scriptPostfix);
  554.         }
  555.         else if (objFunctions[funcNum] . postfixObject)
  556.         {
  557.         Log(" ");
  558.         LogObjectName(objFunctions[funcNum] . postfixObject);
  559.         }
  560.         Log("\n");
  561.     }
  562.     }
  563. }
  564.  
  565. int funcToDo;        /*Function to do*/
  566.  
  567. void DoAllObjFunctionsLater()
  568. /*Deferred routine to do all the setup object functions*/
  569. {
  570.     int funcNum;
  571.  
  572.     for (funcNum = 0; funcNum < nObjFunctions; ++funcNum)
  573.     {
  574.     if (IsList(objFunctions[funcNum] . objectsToDo))
  575.     {
  576.         ThingListPtr runner;
  577.  
  578.         runner = LISTOF(objFunctions[funcNum] . objectsToDo);
  579.         if (runner)
  580.         {
  581.         StartObjFunction(funcNum);
  582.         while (runner)
  583.         {
  584.             DoObjFunctionOnObject(runner -> thing);
  585.             runner = runner -> next;
  586.         }
  587.         FinishObjFunction();
  588.         }
  589.         EmptyList(objFunctions[funcNum] . objectsToDo);
  590.     }
  591.     }
  592. }
  593.  
  594. ObjPtr AddToLaterFunctions(object)
  595. ObjPtr object;
  596. /*Adds object to the function to do later in funcToDo*/
  597. {
  598.     PostfixList(objFunctions[funcToDo] . objectsToDo, object);
  599.     return ObjTrue;
  600. }
  601.  
  602. void DoObjFunction(name)
  603. char *name;
  604. /*Does object function name on all selected objects*/
  605. {
  606.     funcToDo = NameToObjFunction(name);
  607.     if (funcToDo < 0)
  608.     {
  609.     /*No valid function*/
  610.     return;
  611.     }
  612.  
  613.     LogSelectedObjFunction(name);
  614.  
  615.     /*Fill the lists with the functions*/
  616.     ForAllSelectedObjects(AddToLaterFunctions);
  617.  
  618.     DoUniqueTask(DoAllObjFunctionsLater);
  619. }
  620.  
  621. ObjPtr ObjectAction(action)
  622. ObjPtr action;
  623. /*Does the action method of an object action from a menu*/
  624. {
  625.     ObjPtr var;
  626.     int k;
  627.  
  628.     var = GetVar(action, FUNCNAME);
  629.     if (var)
  630.     {
  631.     if (contextHelp)
  632.     {
  633.         /*Give help on the action*/
  634.         ContextHelp(action);
  635.         contextHelp = false;
  636.         MySetCursor(0);
  637.     }
  638.     else
  639.     {
  640.         k = NameToObjFunction(GetString(var));
  641.         if (k >= 0)
  642.         {
  643.         if (objFunctions[k] . varPostfix)
  644.         {
  645.             ObjPtr value;
  646.             value = GetVar(action, VALUE);
  647.             if (value)
  648.             {
  649.             if ((objFunctions[k] . scriptPostfix) &&
  650.                 IsString(value))
  651.             {
  652.                 SAFEFREE(objFunctions[k] . scriptPostfix);
  653.                 objFunctions[k] . scriptPostfix = Alloc(strlen(GetString(value)) + 1);
  654.                 strcpy(objFunctions[k] . scriptPostfix, GetString(value));
  655.             }
  656.             else
  657.             {
  658.                 objFunctions[k] . postfixObject = value;
  659.             }
  660.             }
  661.         }
  662.         DoObjFunction(GetString(var));
  663.         }
  664.     }
  665.     }
  666.     return ObjTrue;
  667. }
  668.  
  669. static ObjPtr RenameReally(owner, newName)
  670. ObjPtr owner;
  671. char *newName;
  672. /*Really renames an object*/
  673. {
  674.     int k;
  675.     ObjPtr object;
  676.  
  677.     object = GetVar(owner, OWNERWINDOW);
  678.  
  679.     k = NameToObjFunction(OF_RENAME);
  680.     if (k >= 0)
  681.     {
  682.     /*See if the name is valid*/
  683.     ObjPtr searchList, results;
  684.  
  685.     searchList = NewList();
  686.     PostfixList(searchList, NewSymbol(NAME));
  687.     PostfixList(searchList, NewString(newName));
  688.     PostfixList(searchList, NewSymbol(CLASSID));
  689.     PostfixList(searchList, GetVar(object, CLASSID));
  690.     results = SearchDatabase(searchList);
  691.  
  692.     if (results && LISTOF(results) && LISTOF(results) -> thing != object)
  693.     {
  694.         /*Name is invalid.  Whine.*/
  695.         WinInfoPtr window;
  696.         ObjPtr name, type;
  697.         char alertString[400];
  698.  
  699.         name = GetVar(object, NAME);
  700.         type = GetVar(object, TYPESTRING);
  701.  
  702.         sprintf(alertString, "There is already a%s %s named %s.  Please choose another name:",
  703.         type ? (ISVOWEL(GetString(type)[0]) ? "n" : "") : "n",
  704.         type ? GetString(type) : "object", newName);
  705.         window = AskUser((WinInfoPtr) object, alertString, RenameReally, GetString(name));
  706.         SetVar((ObjPtr) window, INHIBITLOGGING, ObjTrue);
  707.     }
  708.     else
  709.     {
  710.         /*Name is valid.  Copy the name into the script postfix*/
  711.         objFunctions[k] . postfixObject = NewString(newName);
  712.  
  713.         /*Log it.*/
  714.         LogNoWindow(objFunctions[k] . scriptPrefix);
  715.         LogNoWindow(" ");
  716.         LogNoWindowObjectName(object);
  717.         LogNoWindow(" ");
  718.         LogNoWindowObjectName(objFunctions[k] . postfixObject);
  719.         LogNoWindow("\n");
  720.  
  721.         /*Do it.*/
  722.         globalFuncNum = k;
  723.         DoObjFunctionOnObject(object);
  724.     }
  725.     }
  726. }
  727.  
  728. static ObjPtr RenameObject(object)
  729. ObjPtr object;
  730. /*Renames an object*/
  731. {
  732.     char alertString[400];
  733.     ObjPtr name;
  734.     ObjPtr type;
  735.     WinInfoPtr window;
  736.  
  737.     name = GetVar(object, NAME);
  738.     type = GetVar(object, TYPESTRING);
  739.  
  740.     sprintf(alertString, "Enter the new name for %s %s:",
  741.     type ? GetString(type) : "object", GetString(name));
  742.     window = AskUser((WinInfoPtr) object, alertString, RenameReally, GetString(name));
  743.     SetVar((ObjPtr) window, INHIBITLOGGING, ObjTrue);
  744.  
  745.     return ObjTrue;
  746. }
  747.  
  748. ObjPtr RenameObjectAction(action)
  749. ObjPtr action;
  750. /*Does the action method of an object action from a menu*/
  751. {
  752.     ObjPtr var;
  753.     int k;
  754.  
  755.     var = GetVar(action, FUNCNAME);
  756.     if (var)
  757.     {
  758.     if (contextHelp)
  759.     {
  760.         /*Give help on the action*/
  761.         ContextHelp(action);
  762.         contextHelp = false;
  763.         MySetCursor(0);
  764.     }
  765.     else
  766.     {
  767.         ForAllSelectedObjects(RenameObject);
  768.     }
  769.     }
  770.     return ObjTrue;
  771. }
  772.  
  773. ObjPtr AddToDoubleClickFunction(object)
  774. ObjPtr object;
  775. /*Adds object to its desired double click function*/
  776. {
  777.     ObjPtr var;
  778.     int funcNum;
  779.  
  780.     var = GetVar(object, DOUBLECLICK);
  781.     if (var)
  782.     {
  783.     funcNum = NameToObjFunction(GetString(var));
  784.     if (funcNum < 0)
  785.     {
  786.         ReportError("AddToDoubleClickFunction", "Doubleclick object function not valid");
  787.     }
  788.     else
  789.     {
  790.         PostfixList(objFunctions[funcNum] . objectsToDo, object);
  791.     }
  792.     }
  793.     else
  794.     {
  795.     ReportError("AddToDoubleClickFunction", "No doubleclick object function");
  796.     }
  797.     return ObjTrue;
  798. }
  799.  
  800. void DoDoubleClickFunction()
  801. /*Does an appropriate double click function on all selected objects*/
  802. {
  803.     int funcNum;
  804.  
  805.     /*Distribute all the selected objects in their preferred functions*/
  806.     ForAllSelectedObjects(AddToDoubleClickFunction);
  807.  
  808.     /*Log all the object functions*/
  809.     for (funcNum = 0; funcNum < nObjFunctions; ++funcNum)
  810.     {
  811.     if (IsList(objFunctions[funcNum] . objectsToDo))
  812.     {
  813.         if (LISTOF(objFunctions[funcNum] . objectsToDo))
  814.         {
  815.         LogObjFunction( objFunctions[funcNum] . name,
  816.                 objFunctions[funcNum] . objectsToDo);
  817.         }
  818.     }
  819.     }
  820.  
  821.     /*Do it later*/
  822.     DoUniqueTask(DoAllObjFunctionsLater);
  823. }
  824.  
  825. #ifdef PROTO
  826. Bool ObjFunctionScriptLine(char *line)
  827. #else
  828. Bool ObjFunctionScriptLine(line)
  829. char *line;
  830. #endif
  831. /*If s is a script line, finds out if it is a valid script line for an
  832.   object function.  If so, does it and returns true, otherwise does nothing
  833.   and returns false.  Determines whether it is valid by matching the 
  834.   script prefix*/
  835. {
  836.     int funcNum;
  837.     register char *s, *p, *t;
  838.  
  839.     /*For all possible functions*/
  840.     for (funcNum = 0; funcNum < nObjFunctions; ++funcNum)
  841.     {
  842.     /*Try to match prefix against script*/
  843.     s = line;
  844.     p = objFunctions[funcNum] . scriptPrefix;
  845.  
  846.     SKIPBLANKS(s);
  847.     SKIPBLANKS(p);
  848.  
  849.     while (*p)
  850.     {
  851.         if (isspace(*p))
  852.         {
  853.         SKIPBLANKS(s);
  854.         SKIPBLANKS(p);
  855.         }
  856.         else if (toupper(*p) != toupper(*s))
  857.         {
  858.         /*Failure to match*/
  859.         break;
  860.         }
  861.         else
  862.         {
  863.         ++s;
  864.         ++p;
  865.         }
  866.     }
  867.  
  868.     if (*p == 0)
  869.     {
  870.         ObjPtr list;
  871.         ThingListPtr runner;
  872.         ObjPtr object;
  873.         /*It's a match!  Do this function and return true*/
  874.  
  875.         list = NewList();
  876.  
  877.         do
  878.         {
  879.         object = ERROBJ;
  880.         s = ParseObjectArg(s, &object);
  881.  
  882.         if (object != ERROBJ)
  883.         {
  884.             if (!object)
  885.             {
  886.             ScriptError("An object name is expected here.");
  887.             }
  888.             else
  889.             {
  890.             if (IsIcon(object) && GetVar(object, REPOBJ))
  891.             {
  892.                 object = GetVar(object, REPOBJ);
  893.             }
  894.             PostfixList(list, object);
  895.             }
  896.         }
  897.  
  898.         SKIPBLANKS(s);
  899.         } while (*s++ == ',');
  900.         --s;
  901.  
  902.         if (objFunctions[funcNum] . varPostfix)
  903.         {
  904.         /*Variable postfix, set it.*/
  905.         ObjPtr object;
  906.  
  907.         if (objFunctions[funcNum] . scriptPostfix)
  908.         {
  909.             SAFEFREE(objFunctions[funcNum] . scriptPostfix);
  910.             SKIPBLANKS(s);
  911.         
  912.             objFunctions[funcNum] . scriptPostfix = Alloc(strlen(s) + 1);
  913.             strcpy(objFunctions[funcNum] . scriptPostfix, s);
  914.         }
  915.         else
  916.         {
  917.             ParseObjectArg(s, &object);
  918.             objFunctions[funcNum] . postfixObject = object;
  919.         }
  920.  
  921.         p = 0;
  922.         }
  923.         else
  924.         {
  925.         /*Check postfix*/
  926.         p = objFunctions[funcNum] . scriptPostfix;
  927.  
  928.         if (p)
  929.         {
  930.             SKIPBLANKS(s);
  931.             SKIPBLANKS(p);
  932.  
  933.             while (*p)
  934.             {
  935.             if (isspace(*p))
  936.             {
  937.                 SKIPBLANKS(s);
  938.                 SKIPBLANKS(p);
  939.             }
  940.             else if (toupper(*p) != toupper(*s))
  941.             {
  942.                 /*Failure to match*/
  943.                 break;
  944.             }
  945.             else
  946.             {
  947.                 ++s;
  948.                 ++p;
  949.             }
  950.             }
  951.         }
  952.         }
  953.  
  954.         if (!p || (*p == 0))
  955.         {
  956.         LogObjFunction(objFunctions[funcNum] . name, list);
  957.         StartObjFunction(funcNum);
  958.         runner = LISTOF(list);
  959.         while (runner)
  960.         {
  961.             DoObjFunctionOnObject(runner -> thing);
  962.             runner = runner -> next;
  963.         }
  964.         FinishObjFunction();
  965.         return true;
  966.         }
  967.     }
  968.     }
  969.     return false;
  970. }
  971.  
  972. void FunctionMenu(item)
  973. int item;
  974. /*Does an object function from an IRIS menu call*/
  975. {
  976.     if (item < 0 || item > nObjFunctions)
  977.     {
  978.     ReportError("ObjFunctionMenu", "Internal error: bad menu value");
  979.     return;
  980.     }
  981.  
  982. #ifdef INTERACTIVE
  983.     if (contextHelp)
  984.     {
  985.     /*DIKEO Change to do menus as objects, then add context help*/
  986.     }
  987.     else
  988. #endif
  989.     {
  990.     LogSelectedObjFunction(objFunctions[item] . name);
  991.     StartObjFunction(item);
  992.     ForAllSelectedObjects(DoObjFunctionOnObject);
  993.     FinishObjFunction();
  994.     }
  995. }
  996.  
  997. static WinInfoPtr testWindow = 0;
  998.  
  999. static ObjPtr TestObjFunctions(object)
  1000. ObjPtr object;
  1001. /*Tests the obj functions on object*/
  1002. {
  1003.     int k;
  1004.  
  1005.     if (testWindow && !ObjectWhichRepresents(testWindow, object))
  1006.     {
  1007.     return ObjFalse;
  1008.     }
  1009.  
  1010.     for (k = 0; k < nObjFunctions; ++k)
  1011.     {
  1012.     if (GetMethod(object, objFunctions[k] . funcMessage))
  1013.     {
  1014.         ++objFunctions[k] . isUsed;
  1015.     }
  1016.     }
  1017.     return ObjTrue;
  1018. }
  1019.  
  1020. static ObjPtr MakeObjActionActivated(action)
  1021. ObjPtr action;
  1022. /*Makes an action activated*/
  1023. {
  1024.     ObjPtr allSelected;
  1025.     ThingListPtr runner;
  1026.     int f;
  1027.     ObjPtr var;
  1028.     Bool oneActive;
  1029.  
  1030.     var = GetStringVar("MakeObjActionActivated", action, FUNCNAME);
  1031.     if (!var) return ObjFalse;
  1032.     f = NameToObjFunction(GetString(var));
  1033.     if (f < 0) return ObjFalse;
  1034.  
  1035.     SetVar(action, ACTIVATED, ObjFalse);
  1036.     allSelected = GetListVar("MakeObjActionActivated", action, ALLSELECTED);
  1037.     if (allSelected)
  1038.     {
  1039.     oneActive = false;
  1040.     for (runner = LISTOF(allSelected); runner; runner = runner -> next)
  1041.     {
  1042.         if (GetMethod(runner -> thing, objFunctions[f] . funcMessage))
  1043.         {
  1044.         if (objFunctions[f] . multObjects)
  1045.         {
  1046.             SetVar(action, ACTIVATED, ObjTrue);
  1047.             return ObjTrue;
  1048.         }
  1049.         else if (oneActive)
  1050.         {
  1051.             SetVar(action, ACTIVATED, ObjFalse);
  1052.             return ObjTrue;
  1053.         }
  1054.         else
  1055.         {
  1056.             SetVar(action, ACTIVATED, ObjTrue);
  1057.             oneActive = true;
  1058.         }
  1059.         }
  1060.     }
  1061.     }
  1062.     return ObjTrue;
  1063. }
  1064.  
  1065. void AdjustWindowButtons(window)
  1066. WinInfoPtr window;
  1067. /*Adjusts the object buttons in window*/
  1068. {
  1069.     ObjPtr var;
  1070.     ThingListPtr runner;
  1071.     int k;
  1072.  
  1073.     /*Figure out which object functions are valid*/
  1074.     for (k = 0; k < nObjFunctions; ++k)
  1075.     {
  1076.     objFunctions[k] . isUsed = 0;
  1077.     }
  1078.     testWindow = window;
  1079.     ForAllSelectedObjects(TestObjFunctions);
  1080.  
  1081.     var = GetVar((ObjPtr) window, FUNCTIONBUTTONS);
  1082.     if (var)
  1083.     {
  1084.     runner = LISTOF(var);
  1085.     while (runner)
  1086.     {
  1087.         var = GetStringVar("AdjustWindowButtons", runner -> thing, NAME);
  1088.         if (var)
  1089.         {
  1090.         int k;
  1091.         Bool funcIsUsed;
  1092.         k = NameToObjFunction(GetString(var));
  1093.         if (k >= 0)
  1094.         {
  1095.             funcIsUsed = objFunctions[k] . isUsed &&
  1096.             ((objFunctions[k] . isUsed == 1) ||
  1097.              objFunctions[k] . multObjects);
  1098.             ActivateButton(runner -> thing, 
  1099.             funcIsUsed);
  1100.         }
  1101.         }
  1102.         runner = runner -> next;
  1103.     }
  1104.     }
  1105. }
  1106.  
  1107. void AdjustObjButtons()
  1108. /*Task to change all the object buttons in all the windows*/
  1109. {
  1110.     /*Now go through all the windows adjusting the object buttons*/
  1111.     ForAllWindows(AdjustWindowButtons);    
  1112. }
  1113.  
  1114. ObjPtr ChangeFunctionButton(button)
  1115. ObjPtr button;
  1116. /*Changed value for a function button*/
  1117. {
  1118.     ObjPtr var;
  1119.     var = GetVar(button, NAME);
  1120.     if (var)
  1121.     {
  1122.     DoObjFunction(GetString(var));
  1123.     return ObjTrue;
  1124.     }
  1125.     else
  1126.     {
  1127.     return ObjFalse;
  1128.     }
  1129. }
  1130.  
  1131. static ObjPtr SetFunctionButtonValue(theButton, theValue)
  1132. ObjPtr    theButton, theValue;
  1133. {
  1134.     FuncTyp    changer;
  1135.     ObjPtr    retVal;
  1136.  
  1137.     if (IsInt(theValue))
  1138.     {
  1139.     SetVar(theButton, VALUE, theValue);
  1140.     }
  1141.     else if (IsReal(theValue))
  1142.     {
  1143.     SetVar(theButton, VALUE, NewInt((int) GetReal(theValue)));
  1144.     }
  1145.     else
  1146.     {
  1147.     return ObjFalse;
  1148.     }
  1149.  
  1150.     changer = GetMethod(theButton, CHANGEDVALUE);
  1151.     if (changer)
  1152.     {
  1153.     retVal = (* changer) (theButton);
  1154.     }
  1155.     else
  1156.     {
  1157.     retVal = ObjFalse;
  1158.     }
  1159.     ImInvalid(theButton);
  1160.  
  1161.     return retVal;
  1162. }
  1163.  
  1164. #ifdef PROTO
  1165. ObjPtr NewFunctionButton(WinInfoPtr window, int l, int r, int b, int t, char *name)
  1166. #else
  1167. ObjPtr NewFunctionButton(window, l, r, b, t, name)
  1168. WinInfoPtr window; int l; int r; int b; int t; char *name;
  1169. #endif
  1170. {
  1171.     ObjPtr retVal, var;
  1172.     int whichFunction;
  1173.  
  1174.     whichFunction = NameToObjFunction(name);
  1175.     if (whichFunction < 0) return NULLOBJ;
  1176.  
  1177.     retVal = NewButton(l, r, b, t, name);
  1178.     SetMethod(retVal, SETVAL, SetFunctionButtonValue);
  1179.     SetMethod(retVal, CHANGEDVALUE, ChangeFunctionButton);
  1180.     ActivateButton(retVal, false);
  1181.     if (objFunctions[whichFunction] . buttonHelp)
  1182.     {
  1183.     SetVar(retVal, HELPSTRING, 
  1184.     NewString(objFunctions[whichFunction] . buttonHelp));
  1185.     }
  1186.  
  1187.     var = GetVar((ObjPtr) window, FUNCTIONBUTTONS);
  1188.     if (!var)
  1189.     {
  1190.     var = NewList();
  1191.     SetVar((ObjPtr) window, FUNCTIONBUTTONS, var);
  1192.     }
  1193.     PrefixList(var, retVal);
  1194.  
  1195.     DoUniqueTask(AdjustObjButtons);
  1196.  
  1197.     return retVal;
  1198. }
  1199.  
  1200. void InitObjFunctions()
  1201. /*Initializes the object function system*/
  1202. {
  1203.     int k;
  1204.     ObjPtr action;
  1205.  
  1206.     /*Make the class for object actions*/
  1207.     objectActionClass = NewObject(actionClass, 0L);
  1208.     AddToReferenceList(objectActionClass);
  1209.     SetMethod(objectActionClass, ACTIONMETHOD, ObjectAction);
  1210.     DeclareDependency(objectActionClass, ACTIVATED, ALLSELECTED);
  1211.     SetMethod(objectActionClass, ACTIVATED, MakeObjActionActivated);
  1212.     SetVar(objectActionClass, ACTIVATED, ObjFalse);
  1213.  
  1214.     undoClass = NewObject(NULLOBJ, 0L);
  1215.     AddToReferenceList(undoClass);
  1216.  
  1217.     undoList = NewList();
  1218.     AddToReferenceList(undoList);
  1219.  
  1220.     objFunctions = NULL;
  1221.  
  1222.     DefineObjFunction(OF_PICK_UP, (char *) 0, InitPickUp, PICKUP, 0,
  1223.     "drag", (char *) 0, true,
  1224. "Pressing this button picks up the selected objects.  Once you have picked up \
  1225. the objects, you can drop them into another icon corral by clicking where you want to \
  1226. drop them.  This is useful as a substitute for dragging icons between windows on \
  1227. computers that do not support dragging between windows.",
  1228. "Choosing this menu picks up the selected objects.  Once you have picked up \
  1229. the objects, you can drop them into another icon corral by clicking where you want to \
  1230. drop them.  This is useful as a substitute for dragging icons between windows on \
  1231. computers that do not support dragging between windows.", objectMenu, 1, false);
  1232.     DefineObjFunction(OF_OPEN, (char *) 0, 0, OPEN, 0,
  1233.     "open", (char *) 0, true,
  1234.     "Pressing this button reads the selected files into the Datasets window and opens new file windows \
  1235. for the selected folders.", 
  1236.     "Choosing this menu item reads the selected files into the Datasets window and opens new file windows \
  1237. for the selected folders.", fileMenu, 1, false); 
  1238.     DefineObjFunction(OF_SETFORMAT, (char *) 0, SetUpCollect, COLLECT, ProcessSetFormat,
  1239.     "set format", (char *) 0, true,
  1240.     "Pressing this button opens a dialog window allowing you to set the data format \
  1241. of the selected files.",
  1242.     "Choosing this menu item opens a dialog window allowing you to set the data format \
  1243. of the selected files.", fileMenu, 1, false);
  1244.     DefineObjFunction(OF_SHOW_CONTROLS, (char *) 0, 0, SHOWCONTROLS, 0,
  1245.     "show controls", (char *) 0, true,
  1246.     "Pressing this button opens windows showing controls for each of the selected objects.",
  1247.     "Choosing this menu item opens windows showing controls for each of the selected objects.",
  1248.     objectMenu, 1, false);
  1249.     DefineObjFunction(OF_EDIT_PALETTE, (char *) 0, 0, EDITPALETTE, 0,
  1250.     "edit palette", (char *) 0, true,
  1251.     "Pressing this button opens a window to edit the color palette of each of the selected objects.",
  1252.     "Choosing this menu item opens a window to edit the color palette of each of the selected objects.",
  1253.     objectMenu, 1, false);
  1254.     DefineObjFunction(OF_SHOWINFO, (char *) 0, SetUpCollect, COLLECT, ProcessShowInfo,
  1255.     "show info", (char *) 0, true,
  1256.     "Pressing this button opens a window showing directory information for the selected files.",
  1257.     "Choosing this menu item opens a window showing directory information for the selected files.",
  1258.     fileMenu, 1, false);
  1259.     DefineObjFunction(OF_VISUALIZE, (char *) 0, NewSerializedVisWindow, VISUALIZE, 0,
  1260.     "visualize", (char *) 0, true,
  1261. "Pressing this button visualizes the selected objects \
  1262. together in a new window.  Visualization objects are visualized as they are, and \
  1263. datasets are visualized using their default visualization technique.  Hold down \
  1264. the Alt or Ctrl key to have the visualizations come up turned off by default.  This \
  1265. is useful with complex visualizations if you want to change controls before \
  1266. spending the time drawing the visualizations.",
  1267. "Choosing this menu item visualizes the selected objects \
  1268. together in a new window.  Visualization objects are visualized as they are, and \
  1269. datasets are visualized using their default visualization technique.  Hold down \
  1270. the Alt or Ctrl key to have the visualizations come up turned off by default.  This \
  1271. is useful with complex visualizations if you want to change controls before \
  1272. spending the time drawing the visualizations.", datasetsMenu, 1, false);
  1273.     DefineObjFunction(OF_VISUALIZE_AS, (char *) 0, NewVisAsWindow, VISUALIZEAS, ProcessVisAsList,
  1274.     "visobjectas", (char *) 0, true,
  1275. "Pressing this button opens a window \
  1276. showing all the basic ways of visualizing the selected datasets.  You will \
  1277. then be able to choose the visualization you want to use.",
  1278. "Choosing this menu item opens a window \
  1279. showing all the basic ways of visualizing the selected datasets.  You will \
  1280. then be able to choose the visualization you want to use.", datasetsMenu, 1, false);
  1281.     DefineObjFunction(OF_MODIFY, (char *) 0, SetupModifyList, MODIFY, ProcessModifyList,
  1282.     "modify", (char *) 0, true,
  1283. "Pressing this button opens a window showing all the basic ways to \
  1284. modify the selected datasets.  You will then be able to choose the modification \
  1285. you want to use.",
  1286. "Choosing this menu item opens a window showing all the basic ways to \
  1287. modify the selected datasets.  You will then be able to choose which modification \
  1288. you want to use.", datasetsMenu, 1, false);
  1289.     DefineObjFunction(OF_ACTIVATE, (char *) 0, 0, ACTIVATEOBJECT, 0,
  1290.     "activate", (char *) 0, false,
  1291. "Pressing this button activates the selected object, deactivating any previously activated objects of that class in the window.",
  1292. "Choosing this menu item activates the selected object, deactivating any previously activated objects of that class in the window.", objectMenu, 1, false);
  1293.     DefineObjFunction(OF_TURNON, (char *) 0, 0, SHOW, 0,
  1294.     "turn on", (char *) 0, true,
  1295. "Pressing this button turns on all the selected objects.",
  1296. "Choosing this menu item turns on all the selected objects.", objectMenu, 1, false);
  1297.     DefineObjFunction(OF_TURNOFF, (char *) 0, 0, HIDE, 0,
  1298.     "turn on", (char *) 0, true,
  1299. "Pressing this button turns off all the selected objects.",
  1300. "Choosing this menu item turns off all the selected objects.", objectMenu, 1, false);
  1301.     DefineObjFunction(OF_PUSHTOBOTTOM, (char *) 0, 0, PUSHTOBOTTOM, 0,
  1302.     "push to bottom", (char *) 0, true,
  1303. "Pressing this button pushes the selected space panel drawings to the bottom of the panel \
  1304. below all the others.",
  1305. "Choosing this menu item pushes the selected space panel drawings to the bottom of the panel \
  1306. below all the others.",
  1307.     arrangeMenu, 1, false);
  1308.     DefineObjFunction(OF_BRINGTOTOP, (char *) 0, 0, BRINGTOTOP, 0,
  1309.     "bring to top", (char *) 0, true,
  1310. "Pressing this button brings the selected space panel drawings to the top of the panel \
  1311. above all the others.",
  1312. "Choosing this menu item brings the selected space panel drawings to the top of the panel \
  1313. above all the others.",
  1314.     arrangeMenu, 1, false);
  1315.     DefineObjFunction(OF_MOVETOBACKPANEL, (char *) 0, 0, MOVETOBACKPANEL, 0,
  1316.     "move to back panel", (char *) 0, true,
  1317. "Pressing this button moves the selected space panel drawings to the back panel of the space.",
  1318. "Choosing this menu item moves the selected space panel drawings to the back panel of the space.",
  1319.     arrangeMenu, 1, false);
  1320.     DefineObjFunction(OF_MOVETOFRONTPANEL, (char *) 0, 0, MOVETOFRONTPANEL, 0,
  1321.     "move to front panel", (char *) 0, true,
  1322. "Pressing this button moves the selected space panel drawings to the front panel of the space.",
  1323. "Choosing this menu item moves the selected space panel drawings to the front panel of the space.",
  1324.     arrangeMenu, 1, false);
  1325.     DefineObjFunction(OF_DUPLICATE, (char *) 0, 0, DUPLICATE, 0,
  1326.     "duplicate", (char *) 0, true,
  1327. "Pressing this button duplicates the selected objects in the current window.",
  1328. "Choosing this menu item duplicates the selected objects in the current window.",
  1329.     objectMenu, 1, false);
  1330.     DefineObjFunction(OF_LOCALCOPY, (char *) 0, 0, LOCALCOPY, 0,
  1331.     "localcopy", (char *) 0, true,
  1332. "Pressing this button makes copies of the selected objects local to this window.  \
  1333. If the objects are shared between windows, the new copies will be detached from the shared objects.\n\n\
  1334. For example, if you have a single observer which is in two spaces, produced by \
  1335. dragging the observer from one window to the other, then the one observer will control both spaces.  \
  1336. Any operations on the observer will affect both spaces, because there's really just one observer controlling \
  1337. both spaces.  If you decide that you two observers that word separately, you can select the observer \
  1338. and choose Detach Local Copy from within a window.  A new observer will be created which \
  1339. is just like the old observer but which will be independent of the old observer.",
  1340. "Choosing this menu item makes copies of the selected objects local to this window.  \
  1341. If the objects are shared between windows, the new copies will be detached from the shared objects.\n\n\
  1342. For example, if you have a single observer which is in two spaces, produced by \
  1343. dragging the observer from one window to the other, then the one observer will control both spaces.  \
  1344. Any operations on the observer will affect both spaces, because there's really just one observer controlling \
  1345. both spaces.  If you decide that you two observers that word separately, you can select the observer \
  1346. and choose Detach Local Copy from within a window.  A new observer will be created which \
  1347. is just like the old observer but which will be independent of the old observer.",
  1348.     objectMenu, 1, false);
  1349.     DefineObjFunction(OF_DELETE, (char *) 0, 0, DELETE, 0,
  1350.     "delete", (char *) 0, true,
  1351. "Pressing this button deletes all the selected objects from the \
  1352. window.  If the objects are present in other windows, they will remain in those \
  1353. windows.  An object will not go away completely until it is deleted from everywhere \
  1354. it appears.",
  1355. "Choosing this menu item deletes all the selected objects from the \
  1356. window.  If the objects are present in other windows, they will remain in those \
  1357. windows.  An object will not go away completely until it is deleted from everywhere \
  1358. it appears.",
  1359.     objectMenu, 1, false);
  1360. #ifdef SOCKETS
  1361.     DefineObjFunction(OF_CONNECT_TO_PROCESS, (char *) 0, 0, CONNECTTOPROCESS, 0,
  1362.     "connect to process", (char *) 0, true,
  1363.     "Pressing this button opens a connection with the selected process or processes.", 
  1364.     "Choosing this menu item opens a connection with the selected process or processes.", networkMenu, 1, false); 
  1365.     DefineObjFunction(OF_ADVERTISE, (char *) 0, DoEnablePublication, ADVERTISE, 0,
  1366.     "publish", (char *) 0, true,
  1367.     "Pressing this button publishes the selected objects over the network.", 
  1368.     "Choosing this menu item publishes the selected objects over the network.", networkMenu, 1, false); 
  1369.     DefineObjFunction(OF_UNADVERTISE, (char *) 0, 0, UNADVERTISE, 0,
  1370.     "recall", (char *) 0, true,
  1371.     "Pressing this button recalls the selected objects from publication over the network.", 
  1372.     "Choosing this menu item recalls the selected objects from publication over the network.", networkMenu, 1, false); 
  1373. #endif
  1374.  
  1375.     DefineObjFunction(OF_ALIGNLEFT, (char *) 0, 0, ALIGNLEFT, 0,
  1376.     "align left", (char *) 0, true,
  1377.     "Pressing this button aligns the text in the selected text boxes to the left margin.", 
  1378.     "Choosing this menu item aligns the text in the selected text boxes to the left margin.", 
  1379.     alignMenu, 1, false); 
  1380.  
  1381.     DefineObjFunction(OF_ALIGNCENTER, (char *) 0, 0, ALIGNCENTER, 0,
  1382.     "align center", (char *) 0, true,
  1383.     "Pressing this button will center the text in the selected text boxes.", 
  1384.     "Choosing this menu item will center the text in the selected text boxes.", 
  1385.     alignMenu, 1, false); 
  1386.  
  1387.     DefineObjFunction(OF_ALIGNRIGHT, (char *) 0, 0, ALIGNRIGHT, 0,
  1388.     "align right", (char *) 0, true,
  1389.     "Pressing this button aligns the text in the selected text boxes to the right margin.", 
  1390.     "Choosing this menu item aligns the text in the selected text boxes to the right margin.", 
  1391.     alignMenu, 1, false);
  1392.  
  1393.     action = DefineObjFunction(OF_RENAME, (char *) 0, 0, RENAME, 0,
  1394.     "rename", (char *) 0, false,
  1395.     "Pressing this button lets you rename the selected object.",
  1396.     "Choosing this menu item lets you rename the selected object.",
  1397.     objectMenu, 1, true);
  1398.     SetMethod(action, ACTIONMETHOD, RenameObjectAction);
  1399.  
  1400. #ifdef FONTS4D
  1401.     for (k = 0; k < sizeof(textSizes) / sizeof(int); ++k)
  1402.     {
  1403.     char numBuf[20];
  1404.     sprintf(numBuf, "%d", textSizes[k]);
  1405.  
  1406.     action = DefineObjFunction(OF_SETFONTSIZE, numBuf, 0, SETTEXTSIZE, 0,
  1407.         "set size", (char *) 0, true,
  1408.         "Pressing this button sets the text size of selected objects to %s points.",
  1409.         "Choosing this menu item sets the text size of selected objects to %s points.",
  1410.         fontSizeMenu, 1, true);
  1411.     SetVar(action, VALUE, NewInt(textSizes[k]));
  1412.     }
  1413. #endif
  1414.  
  1415.     if (nFonts)
  1416.     {
  1417.     int k;
  1418.     ObjPtr subMenu;
  1419.     char mainFontName[300];
  1420.     char *s, *d, *f;
  1421.  
  1422.     strcpy(mainFontName, "");
  1423.     subMenu = NULLOBJ;
  1424.  
  1425.     for (k = 0; k < nFonts; ++k)
  1426.     {
  1427.         Bool matches;
  1428.         f = strchr(fonts[k], '-');
  1429.  
  1430.         /*See if this one matches what's in the main font name*/
  1431.         if (mainFontName[0])
  1432.         {
  1433.         s = mainFontName;
  1434.         d = fonts[k];
  1435.         while (*s == *d)
  1436.         {
  1437.             ++s;
  1438.             ++d;
  1439.         }
  1440.  
  1441.         if (d == f || *d == 0)
  1442.         {
  1443.             matches = true;
  1444.         }
  1445.         else
  1446.         {
  1447.             matches = false;
  1448.         }
  1449.         }
  1450.         else
  1451.         {
  1452.         matches = false;
  1453.         }
  1454.  
  1455.         /*See if we need to finish up old font*/
  1456.         if (mainFontName[0] && !matches)
  1457.         {
  1458.         if (subMenu)
  1459.         {
  1460.             /*Put on the old menu as a submenu*/
  1461.             AddMenuItem(fontMenu, subMenu, 1);
  1462.             subMenu = NULLOBJ;
  1463.         }
  1464.         else
  1465.         {
  1466.             /*Just alone*/
  1467.             DefineObjFunction(OF_SETFONT, mainFontName, 0, SETTEXTFONT, 0,
  1468.             "set font", mainFontName, true,
  1469.             "Pressing this button sets the font of selected objects to %s.",
  1470.             "Choosing this menu item sets the font of selected objects to %s.",
  1471.             fontMenu, 1, true);
  1472.         }
  1473.         mainFontName[0] = 0;
  1474.         }
  1475.  
  1476.         if (!mainFontName[0])
  1477.         {
  1478.         /*It's a new main font name.  Copy it in*/
  1479.         s = fonts[k];
  1480.         d = mainFontName;
  1481.         if (f)
  1482.         {
  1483.             while (s < f)
  1484.             {
  1485.             *d++ = *s++;
  1486.             }
  1487.         }
  1488.         else
  1489.         {
  1490.             while (*s)
  1491.             {
  1492.             *d++ = *s++;
  1493.             }
  1494.         }
  1495.         *d = 0;
  1496.  
  1497.         matches = true;
  1498.  
  1499.         if (f)
  1500.         {
  1501.             /*We know there are more than one; make a new submenu*/
  1502.             subMenu = NewMenu(mainFontName);
  1503.             /*Now add us*/
  1504.             DefineObjFunction(OF_SETFONT, f ? (f + 1) : "Plain", 0, SETTEXTFONT, 0,
  1505.             "set font", fonts[k], true,
  1506.             "Pressing this button sets the font of selected objects to %s.",
  1507.             "Choosing this menu item sets the font of selected objects to %s.",
  1508.             subMenu, 1, true);
  1509.         }
  1510.         else
  1511.         {
  1512.             /*This may be the only one.  Don't make a submenu*/
  1513.         }
  1514.         }
  1515.         else
  1516.         {
  1517.         /*It matches a current main font.*/
  1518.  
  1519.         if (!subMenu)
  1520.         {
  1521.             /*Create a submenu if it's not there, with Plain*/
  1522.             subMenu = NewMenu(mainFontName);
  1523.             DefineObjFunction(OF_SETFONT, "Plain", 0, SETTEXTFONT, 0,
  1524.             "set font", fonts[k - 1], true,
  1525.             "Pressing this button sets the font of selected objects to %s.",
  1526.             "Choosing this menu item sets the font of selected objects to %s.",
  1527.             subMenu, 1, true);
  1528.         }
  1529.  
  1530.         /*Now add us*/
  1531.         DefineObjFunction(OF_SETFONT, f ? (f + 1) : "Plain", 0, SETTEXTFONT, 0,
  1532.             "set font", fonts[k], true,
  1533.             "Pressing this button sets the font of selected objects to %s.",
  1534.             "Choosing this menu item sets the font of selected objects to %s.",
  1535.             subMenu, 1, true);
  1536.         }
  1537.     }
  1538.     /*See if we need to finish up old font*/
  1539.     if (subMenu)
  1540.     {
  1541.         AddMenuItem(fontMenu, subMenu, 1);
  1542.         subMenu = NULLOBJ;
  1543.     }
  1544.     else
  1545.     {
  1546.         /*Just alone*/
  1547.         DefineObjFunction(OF_SETFONT, mainFontName, 0, SETTEXTFONT, 0,
  1548.         "set font", mainFontName, true,
  1549.         "Pressing this button sets the font of selected objects to %s.",
  1550.         "Choosing this menu item sets the font of selected objects to %s.",
  1551.         fontMenu, 1, true);
  1552.     }
  1553.     }
  1554. }
  1555.  
  1556. void KillObjFunctions()
  1557. {
  1558.     RemoveFromReferenceList(undoList);
  1559.     RemoveFromReferenceList(undoClass);
  1560.     while (nObjFunctions)
  1561.     {
  1562.     --nObjFunctions;
  1563.     if (objFunctions[nObjFunctions] . name)
  1564.     {
  1565.         Free(objFunctions[nObjFunctions] . name);
  1566.     }
  1567.     if (objFunctions[nObjFunctions] . scriptPrefix)
  1568.     {
  1569.         Free(objFunctions[nObjFunctions] . scriptPrefix);
  1570.     }
  1571.      if (objFunctions[nObjFunctions] . scriptPostfix)
  1572.     {
  1573.         Free(objFunctions[nObjFunctions] . scriptPostfix);
  1574.     }
  1575.      if (objFunctions[nObjFunctions] . buttonHelp)
  1576.     {
  1577.         Free(objFunctions[nObjFunctions] . buttonHelp);
  1578.     }
  1579.       if (objFunctions[nObjFunctions] . menuHelp)
  1580.     {
  1581.         Free(objFunctions[nObjFunctions] . menuHelp);
  1582.     }
  1583.     DeleteThing(objFunctions[nObjFunctions] . objectsToDo);
  1584.     }
  1585.     if (objFunctions)
  1586.     {
  1587.     Free(objFunctions);
  1588.     }
  1589.     RemoveFromReferenceList(objectActionClass);
  1590. }
  1591.